﻿// for trace function
var show = function (str) {
    var body = window.document.body;
    var p = document.createElement("p");
    var content = document.createTextNode(str);
    p.appendChild(content);
    body.appendChild(p);
};

function _tt() {
    var trace = false;
    var f = function (str2) {
        if (!trace) { trace = true; show("Tracing........................................."); }
        show(str2);
    };
    return f;
}
Trace = _tt();
// end trace function
function MoveASet(aSet, dx, dy) {
    if (aSet.items) {
        for (var i = 0, ii = aSet.items.length; i < ii; i++) {
            var ox = 0, oy = 0;
            var myobj = aSet.items[i];
            if (myobj.type == "ellipse" || myobj.type == "circle") {
                ox = myobj.attrs.cx;
                oy = myobj.attrs.cy;
                myobj.attr({ cx: ox + dx, cy: oy + dy });
            } else {
                ox = myobj.attrs.x;
                oy = myobj.attrs.y;
                myobj.attr({ x: ox + dx, y: oy + dy });
            }
        }
    }
};


// core .............................................................................
function SetupTiUp(canvas) {
    function TiUp() {

        var p = canvas.path("M 0 0 l 0 478 l 1160 0 l 0 -478 l -1160 0 z");
        p.attr({ fill: ' #FFFFF0' });

        TiUpClass = TiUp.prototype;
        

      

        //class  Pair
        function Pair(first, second) {
            this.first = first;
            this.second = second;
        }
        Pair.prototype.IsEqualTo = function (other) {
            return (this.first == other.first && this.second == other.second);   // the same obj       
        }
        //end of class  Pair


        //class FriendPair : Pair
        function FriendPair(first, second) {
            Pair.call(this, first, second);
        }
        FriendPair.prototype = new Pair();
        FriendPair.prototype.IsEqualTo = function (other) {
            return (this.first == other.first && this.second == other.second) ||
             (this.first == other.second && this.first == other.second);   // the same obj       
        }
        //end of class FriendPair 



        // Map begins.................................................
        var Map = function () {
            this._keys = [];
            this._values = [];
        };

        Map.prototype.clear = function () {
            this._keys = [];
            this._values = [];
        };

        Map.prototype.getValue = function (key) {
            var index = this._indexOf(key, this._keys);
            if (index != -1) {
                return this._values[index];
            }
            return undefined;
        };

        Map.prototype.getKey = function (value) {
            var index = this._indexOf(value, this._values);
            if (index != -1) {
                return this._keys[index];
            }
            return undefined;
        };

        Map.prototype.hasKey = function (key) {
            return (this._indexOf(key, this._keys) != -1);
        };

        Map.prototype.hasValue = function (value) {
            return (this._indexOf(value, this._values) != -1);
        };

        Map.prototype.put = function (key, value) {
            var index = this._indexOf(key, this._keys);
            if (index == -1) {
                index = this._keys.length;
            }
            this._keys[index] = key;
            this._values[index] = value;
        };

        Map.prototype.remove = function (key) {
            var index = this._indexOf(key, this._keys);
            if (index != -1) {
                this._keys.splice(index, 1);
                this._values.splice(index, 1);
            }
        };
        Map.prototype.size = function () {
            return this._keys.length;
        };
        Map.prototype._indexOf = function (item, list) {
            for (var i = 0, l = list.length; i < l; i++) {
                if (this._equals(list[i], item)) {
                    return i;
                }
            }
            return -1;
        };
        Map.prototype._equals = function (a, b) {             /// customor data structures should provide a  IsEqualTo function
            if (typeof a.IsEqualTo == "undefined") return (a == b);
            if (a.IsEqualTo(b)) {
                return true;
            }
            return false;
        };  // Map ends .....................................

        // class circle begins
        var GetName = function () { return this.Name; }
        var CircleStart = function () {
            this.ox = this.attr("cx");
            this.oy = this.attr("cy");
        };
        var CircleMove = function (dx, dy) {
            this.attr({ opacity: .3 });
            this.attr({ cx: dx + this.ox, cy: dy + this.oy });
            LM.UpdateRelatedLines(this);
        };
        var CircleUp = function () {
            this.attr({ opacity: 1 });
        };
        TiUpClass.Circle = function (x, y, r, name) {
            //alert("adfas");
            var c = canvas.circle(x, y, r);
            c.Name = name;
            Trace("GetName:  " + typeof GetName);
            c.GetName = GetName;
            c.drag(CircleMove, CircleStart, CircleUp);
            return c;
        }; //end of Circle




        // class FriendBox  begins


        TiUpClass.FriendBox = function(path, name, x, y, w, h, r) {
            var t = canvas.text(100, 200, "fuck you ");
            t.toFront();

            //---------draw text & image & rect
            var f = canvas.set();
            var attr = { font: '12px Helvetica, Arial', opacity: 0.5 };
            var text = canvas.text(x, y, name).attr(attr);

            var image= canvas.image(path, x - 10, y - 28, 20, 20);
            f.push(text, image);

            var w = f.getBBox().width;
            var a = w / 2;
            var h = f.getBBox().height;
            var rect = canvas.rect(x - a, y - 29, w, h, r);
            rect.attr({ fill: '#FFFFF0', stroke: 'none' });


            //---------for the mouseover
            var tx = x - 10 - 5;
            var ty = y - 28 - 5;

            //---------get rid of the backgroud
            f.push(text, image, rect);
            f[0].toFront();
            f[1].toFront();
            f[2].toFront();

            //------------events
            f.mouseover(function(event) {

                //change cursor to pointer  
                text.node.style.cursor = 'pointer';
                rect.node.style.cursor = 'pointer';
                image.node.style.cursor = 'pointer';

            //---------Highlighting the image   
                f[1].attr({ x: tx, y: ty, width: '30', height: '30' });
                // f[1].attr({ x: x, y: y, width: '30', height: '30' });
                f[1].attr({ width: '30', height: '30' });
                rect.attr({ stroke: 'red' });

            //---------Highlighting the line
                var rl = [];
                rl = LM.GetRelatedLines(f);
                for (var i = 0, l = rl.length; i < l; i++) {
                    rl[i].attr({ stroke: 'red' });
                }
            });
            f.mouseout(function(event) {
                f[1].attr({ x: tx + 5, y: ty + 5, width: '20', height: '20' });
                rect.attr({ stroke: "none" });

                var rl = [];
                rl = LM.GetRelatedLines(f);
                for (var i = 0, l = rl.length; i < l; i++) {
                    rl[i].attr({ stroke: 'black' });
                }

            });

            rect.node.oncontextmenu = function() {
                alert("fuck");
                return false;
            }
            image.node.oncontextmenu = function() {
                alert("fuck");
                return false;
            }
            
//          rect.click(function(event) {   
//               alert("fuck");
//            });

            image.click(function(event) {
               alert("fuck");
            });

        //---------attribute
            rect.container = f;

            f.attrs = {};
            f.attrs.w = w;
            f.attrs.h = h;

            f.attrs.cx = x;       //center point of set
            f.attrs.cy = y - 18;  // cener point of set


       //-------these three functions for rect.drag
            var FriendBoxStart = function() {
                this.ox = this.attr("x");
                this.oy = this.attr("y");
            };

            var FriendBoxMove = function(dx, dy) {
                this.container.attr({ opacity: .3 });
                px = dx + this.ox;
                py = dy + this.oy;
                this.attr({ x: px, y: py });

                var newTextX = (px + this.container.attrs.w / 2);
                var newTextY = (py + 29);
                var newImageX = (px + this.container.attrs.w / 2 - 10);

                this.container.attrs.cx = newTextX;    //center point of set
                this.container.attrs.cy = (py + 10);  // cener point of set

                this.container.items[0].attr({ x: newTextX, y: newTextY });
                this.container.items[1].attr({ x: newImageX, y: py });

                //tx & ty make sure that image stay where they are
                tx = newImageX - 5;
                ty = py - 5;

                LM.UpdateRelatedLines(this.container);
            };

            var FriendBoxUp = function() {
                this.container.attr({ opacity: 1 });

            };

            rect.drag(FriendBoxMove, FriendBoxStart, FriendBoxUp);

            return f;

        }
        // class FriendBox  ends


        // class Line begines
        var FormatLineSVGPath = function (x1, y1, x2, y2) {
            return ("M" + x1.toString() + " " + y1.toString() + "L" + x2.toString() + " " + y2.toString());
        };
        var LineSVGPath = function () {
            return FormatLineSVGPath(this.attrs.x1, this.attrs.y1, this.attrs.x2, this.attrs.y2);
        };
        var  IsEqualTo=function (l) {
        return ( (this.obj1==l.obj1 && this.obj2== l.obj2) || (this.obj1==l.obj2 && this.obj2== l.obj1) );
        }
        var UpdatePosition = function() {
        this.attr({ "path": FormatLineSVGPath(this.obj1.attrs.cx, this.obj1.attrs.cy, this.obj2.attrs.cx, this.obj2.attrs.cy) });
            //this.attr({ pathString: FormatLineSVGPath(this.obj1.attrs.cx, this.obj1.attrs.cy, this.obj2.attrs.cx, this.obj2.attrs.cy) });
            p = FormatLineSVGPath(this.obj1.attrs.cx, this.obj1.attrs.cy, this.obj2.attrs.cx, this.obj2.attrs.cy);     
            this.attr({ pathString: p });
            
        }
        TiUpClass.Line = function(obj1, obj2) {         //   obj1 obj2 should has obj.attrs.cx obj.attrs.cy (center point)
            var p = canvas.path(FormatLineSVGPath(obj1.attrs.cx, obj1.attrs.cy, obj2.attrs.cx, obj2.attrs.cy));
            p.attrs.x1 = obj1.attrs.cx;
            p.attrs.x2 = obj2.attrs.cx;
            p.attrs.y1 = obj1.attrs.cy;
            p.attrs.y2 = obj2.attrs.cy;
            p.obj1 = obj1;
            p.obj2 = obj2;
            p.LineSVGPath = LineSVGPath;
            p.IsEqualTo = IsEqualTo;
            p.UpdatePosition = UpdatePosition;
            //p.toBack();
            //p.toFront();
            return p;
        };      //end of Line

        // LineManagement
        var LineManagement = function () {            
            this.lines = [];
        };
        LineManagement.prototype.AddLine= function (line) {
                if (! this.LineExist (line)) {   this.lines.push(line);   }
        };
        LineManagement.prototype.LineExist = function (line) {
            if (this.IndexOf(line) != -1) return true;
            return false;
        };
        LineManagement.prototype.IndexOf= function (line){
                for (var i = 0, l = this.lines.length; i < l; i++) {
                    if (  line.IsEqualTo(this.lines[i] )  )   return i;                        
                }
                return -1;
        }
        LineManagement.prototype.GetRelatedLines=function (obj) {
            var ls = [];
                for (var i = 0, l = this.lines.length; i < l; i++) {
                    if (  this.lines[i].obj1==obj || this.lines[i].obj2==obj  ) ls.push(this.lines[i]);                        
                }
                return ls;
        };
        LineManagement.prototype.UpdateRelatedLines = function (obj) {
            var ls = this.GetRelatedLines(obj);
            for (var i = 0, l = ls.length; i < l; i++) {
            ls[i].UpdatePosition();                                              
            }                       
        };  // LineManagement end



    window.LM = new LineManagement();
    }; // function TiUp
    window.TiUp = new TiUp();
    
}; // SetupTiUp